package com.example.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.example.blog.base.CurrentAccount;
import com.example.blog.common.StatusEnums;
import com.example.blog.entity.Follow;
import com.example.blog.entity.SysUser;
import com.example.blog.entity.vo.follow.FollowDetailInfoVO;
import com.example.blog.mapper.FollowMapper;
import com.example.blog.service.FollowService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.blog.service.SysUserService;
import com.example.blog.util.BeanUtils;
import com.example.blog.util.CurrentUserUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 关注表 服务实现类
 * </p>
 *
 * @author wlh
 * @since 2024-01-10
 */
@Service
public class FollowServiceImpl extends ServiceImpl<FollowMapper, Follow> implements FollowService {


    @Autowired
    @Lazy
    private SysUserService sysUserService;
    @Override
    public void add(Long userId) {
        CurrentAccount currentUser = CurrentUserUtils.currentUser();
        Follow follow = new Follow();
        follow.setFollowerId(currentUser.getId());
        follow.setFollowingId(userId);
        follow.setIsRead(StatusEnums.NOT_READ.getValue());

        save(follow);
    }

    @Override
    public void del(Long userId) {
        CurrentAccount currentUser = CurrentUserUtils.currentUser();
        LambdaUpdateWrapper<Follow> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Follow::getFollowerId, currentUser.getId())
                .eq(Follow::getFollowingId, userId);

        remove(updateWrapper);
    }

    @Override
    public Long getNewCountByUser(Long userId) {
        LambdaQueryWrapper<Follow> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(Follow::getFollowingId, userId)
                .eq(Follow::getIsRead, StatusEnums.NOT_READ.getValue());

        return count(queryWrapper);
    }

    @Override
    public List<FollowDetailInfoVO> newFollow() {

        CurrentAccount currentUser = CurrentUserUtils.currentUser();
        LambdaQueryWrapper<Follow> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(Follow::getFollowingId, currentUser.getId())
                .orderByAsc(Follow::getIsRead)
                .orderByDesc(Follow::getCreatedTime)
        ;

        List<Follow> list = list(queryWrapper);
        if (list.isEmpty()) {
            return new ArrayList<>();
        }
        List<Long> ids = list
                .stream()
                .map(Follow::getFollowerId)
                .toList();

        Map<Long, SysUser> userMap = sysUserService.listByIds(ids)
                .stream()
                .collect(Collectors.toMap(SysUser::getId, Function.identity()));


        return list.stream()
                .map(follow -> {
                    FollowDetailInfoVO followDetailInfoVO = BeanUtils.copyProperties(follow, FollowDetailInfoVO.class);
                    SysUser sysUser = userMap.get(follow.getFollowerId());
                    if (sysUser != null) {
                        BeanUtils.copyProperties(sysUser,followDetailInfoVO, false);
                    }
                    return followDetailInfoVO;
                })
                .toList();
    }

    @Override
    public void read() {

        CurrentAccount currentUser = CurrentUserUtils.currentUser();
        LambdaUpdateWrapper<Follow> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Follow::getFollowingId, currentUser.getId())
                .eq(Follow::getIsRead, StatusEnums.NOT_READ.getValue())
                .set(Follow::getIsRead, StatusEnums.READ.getValue());
        update(updateWrapper);
    }

    @Override
    public Long countByUser(Long userId) {

        LambdaQueryWrapper<Follow> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(Follow::getFollowingId, userId);

        return count(queryWrapper);

    }

    @Override
    public Boolean isFollowed(Long currentUserId, Long targetUserId) {

        LambdaQueryWrapper<Follow> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Follow::getFollowerId, currentUserId)
                .eq(Follow::getFollowingId, targetUserId);
        return count(queryWrapper) > 0;
    }

    @Override
    public List<Follow> getListByUser(Long currentUserId, List<Long> uids) {
        return list(new LambdaQueryWrapper<Follow>()
                .eq(Follow::getFollowerId, currentUserId)
                .in(Follow::getFollowingId, uids));
    }
}
